/*
 * This file (AxParametersDialog.java) is protected by the GNU GPL licence (v2). 
 * Please read the license.txt attached for further informations. 
 * 
 */

package artx.gui;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

import artx.objects.AxParameterManager;
import artx.parameters.AxBoolParameter;
import artx.parameters.AxParameter;
import artx.utils.AxLog;

/**
 * Standard dialog to edit a list of parameter.
 * 
 * @author Xavier Gouchet
 * 
 */
public class AxParamsDlg extends JDialog implements ActionListener {

	private static final long serialVersionUID = 1L;

	private JPanel mainPanel = null;

	private JScrollPane scrollPane = null;

	private JPanel contentPanel = null;

	private AxParameterManager paramMngr;

	private ArrayList<AxParameter> parameters;

	private ArrayList<JComponent> components;

	private JButton okBttn = null;

	private JButton resetBttn = null;

	private JButton defaultBttn = null;

	private JButton cancelBttn = null;

	/**
	 * Standard constructor.
	 * 
	 * @param owner
	 *            the master window calling this dialog
	 * @param title
	 *            the title of the dialog
	 * @param params
	 *            the parameter manager from which the dialog will be built
	 */
	public AxParamsDlg(Frame owner, String title, AxParameterManager params) {
		super(owner);
		this.paramMngr = params;
		this.parameters = this.paramMngr.GetParameters();
		this.setTitle(title);
		this.setContentPane(getMainPanel());
		this.pack();
	}

	private JPanel getMainPanel() {
		if (this.mainPanel == null) {
			this.mainPanel = new JPanel();
			this.mainPanel.setLayout(new FlowLayout());
			this.mainPanel.add(this.getScrollPane());
		}
		return this.mainPanel;
	}

	private JScrollPane getScrollPane() {
		if (this.scrollPane == null) {
			this.scrollPane = new JScrollPane();
			this.scrollPane.setPreferredSize(new Dimension(250, 300));
			this.scrollPane
					.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
			this.scrollPane
					.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
			this.scrollPane.setViewportView(this.getContentPanel());
		}
		return this.scrollPane;
	}

	private JPanel getContentPanel() {
		if (this.contentPanel == null) {
			this.contentPanel = new JPanel();
			this.contentPanel.setLayout(new GridBagLayout());

			int row = this.BuildContent();
			this.BuildButtons(row);
		}
		return this.contentPanel;
	}

	private int BuildContent() {
		int row = 0;
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.insets = new Insets(2, 2, 2, 2);
		if ((this.parameters == null) || (this.parameters.size() == 0)) {
			gbc.gridx = 0;
			gbc.gridwidth = 4;
			JLabel label = new JLabel("No parameters to edit...");
			contentPanel.add(label, gbc);
			row++;
		} else {
			this.components = new ArrayList<JComponent>();
			for (int i = 0; i < this.parameters.size(); i++) {
				AxParameter param = this.parameters.get(i);
				gbc.gridy++;
				gbc.gridx = 0;
				gbc.gridwidth = 1;
				gbc.fill = GridBagConstraints.BOTH;
				String name = param.GetName();
				JLabel plabel = new JLabel(name.toUpperCase().charAt(0)
						+ name.substring(1));
				plabel.setAlignmentY(0);
				contentPanel.add(plabel, gbc);
				gbc.gridx = 1;
				row++;
				if (param.GetType().equals("bool")) {
					gbc.gridwidth = 1;
					JCheckBox pVal = new JCheckBox();
					AxBoolParameter bParam = (AxBoolParameter) param;
					pVal.setSelected(bParam.GetValue());
					contentPanel.add(pVal, gbc);
					this.components.add(pVal);
					continue;
				}
				if (param.GetType().equals("float")) {
					gbc.gridwidth = 1;
					JTextField pVal = new JTextField();
					pVal.setText(param.GetStringValue());
					contentPanel.add(pVal, gbc);
					this.components.add(pVal);
					continue;
				}
				if (param.GetType().equals("int")) {
					gbc.gridwidth = 1;
					JTextField pVal = new JTextField();
					pVal.setText(param.GetStringValue());
					contentPanel.add(pVal, gbc);
					this.components.add(pVal);
					continue;
				}
				gbc.gridwidth = 2;
				JTextField pVal = new JTextField();
				pVal.setText(param.GetStringValue());
				contentPanel.add(pVal, gbc);
				this.components.add(pVal);

			}
		}
		return row;
	}

	private void BuildButtons(int row) {
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.gridy = row;
		gbc.insets = new Insets(2, 2, 2, 2);
		gbc.fill = GridBagConstraints.VERTICAL;
		Dimension btnDim = new Dimension(75, 30);

		gbc.gridx = 0;
		this.okBttn = new JButton("Ok");
		this.okBttn.setPreferredSize(btnDim);
		this.okBttn.addActionListener(this);
		this.contentPanel.add(this.okBttn, gbc);
		gbc.gridx = 1;
		this.resetBttn = new JButton("Reset");
		this.resetBttn.setPreferredSize(btnDim);
		this.resetBttn.addActionListener(this);
		this.contentPanel.add(this.resetBttn, gbc);
		gbc.gridx = 2;
		this.cancelBttn = new JButton("Cancel");
		this.cancelBttn.setPreferredSize(btnDim);
		this.cancelBttn.addActionListener(this);
		this.contentPanel.add(this.cancelBttn, gbc);
	}

	private void CloseDialog() {
		this.setVisible(false);
	}

	private void ResetFields() {
		if ((this.parameters == null) || (this.components == null)) {
			AxLog.Warning("Parameters are unavailable, ignoring");
			return;
		}
		for (int i = 0; i < this.parameters.size(); i++) {
			AxParameter param = this.parameters.get(i);
			JComponent component = this.components.get(i);
			AxLog.Debug("AxParamsDlg::ResetFields =>> resetting parameter \""
					+ param.GetName() + "\"");
			if (param.GetType().equals("bool")) {
				JCheckBox pVal = (JCheckBox) component;
				AxBoolParameter bParam = (AxBoolParameter) param;
				if ((pVal != null) && (bParam != null)) {
					pVal.setSelected(bParam.GetValue());
				} else {
					AxLog.Error("Incompatible Class");
				}
			} else {
				JTextField pVal = (JTextField) component;
				if (pVal != null) {
					pVal.setText(param.GetStringValue());
				}
			}
		}
	}

	private void DefaultFields() {
		if ((this.parameters == null) || (this.components == null)) {
			AxLog.Warning("Parameters are unavailable, ignoring");
			return;
		}
		for (int i = 0; i < this.parameters.size(); i++) {
			AxParameter param = this.parameters.get(i);
			JComponent component = this.components.get(i);
			AxLog.Debug("AxParamsDlg::DefaultFields =>> resetting parameter \""
					+ param.GetName() + "\"");
			if (param.GetType().equals("bool")) {
				JCheckBox pVal = (JCheckBox) component;
				AxBoolParameter bParam = new AxBoolParameter("temp", param
						.GetResetValue());
				if ((pVal != null) && (bParam != null)) {
					pVal.setSelected(bParam.GetValue());
				}
			} else {
				JTextField pVal = (JTextField) component;
				if (pVal != null) {
					pVal.setText(param.GetResetValue());
				}
			}
		}
	}

	private void ApplyFields() {
		if ((this.parameters == null) || (this.components == null)) {
			AxLog.Warning("Parameters are unavailable, ignoring");
			return;
		}
		for (int i = 0; i < this.parameters.size(); i++) {
			AxParameter param = this.parameters.get(i);
			JComponent component = this.components.get(i);
			AxLog.Debug("AxParamsDlg::ApplyFields =>> applying new value on "
					+ "parameter \"" + param.GetName() + "\"");
			if (param.GetType().equals("bool")) {
				JCheckBox pVal = (JCheckBox) component;
				if (pVal != null) {
					if (pVal.isSelected()) {
						param.SetValue("true");
					} else {
						param.SetValue("false");
					}
				}
			} else {
				JTextField pVal = (JTextField) component;
				if (pVal != null) {
					param.SetValue(pVal.getText());
				}
			}
		}
	}

	/**
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent e) {
		AxLog.Debug("AxParamsDlg::actionPerformed =>> received callback \""
				+ e.getActionCommand() + "\"");
		if (e.getActionCommand().toLowerCase().equals("ok")) {
			this.ApplyFields();
			this.CloseDialog();
			return;
		}
		if (e.getActionCommand().toLowerCase().equals("reset")) {
			this.ResetFields();
		}
		if (e.getActionCommand().toLowerCase().equals("default")) {
			this.DefaultFields();
		}
		if (e.getActionCommand().toLowerCase().equals("cancel")) {
			this.CloseDialog();
		}
	}
}
